package zlog

import (
    "context"
    "fmt"
    "io"
    "net/http"
    "strconv"
    "strings"
    "sync"
    "time"
)

const (
    wrap      = "\n"
    splicing  = "  "
    separator = "="
)

type zLog struct {
    config  Config
    writers sync.Map
}

var zlog *zLog

// NewZLog 实例zLog
func NewZLog(config Config) {
    zlog = &zLog{
        config:  config,
        writers: sync.Map{},
    }

}

// Config 日志配置
type Config struct {
    Dir    string `json:"dir"`
    Format string `json:"format"` //  格式可选 text|json
}

// Logger 日志
type Logger struct {
    name   string
    ctx    context.Context
    rq     *http.Request
    sn     string
    flag   string
    prefix string
    suffix string
    writer io.Writer
}

// NewHttpLogger 实例HttpLogger
func NewHttpLogger(ctx context.Context, name string, rq *http.Request) *Logger {
    return &Logger{
        name:   name,
        ctx:    ctx,
        rq:     rq,
        sn:     sn(),
        flag:   "",
        prefix: "",
        suffix: fmt.Sprintf("%s", rq.URL),
        writer: writers(name),
    }
}

// NewRpcLogger 实例RpcLogger
func NewRpcLogger(ctx context.Context, name string) *Logger {
    return NewLogger(ctx, name)
}

// NewScriptLogger 实例ScriptLogger
func NewScriptLogger(ctx context.Context, name string) *Logger {
    return NewLogger(ctx, name)
}

// NewCrontabLogger 实例CrontabLogger
func NewCrontabLogger(ctx context.Context, name string) *Logger {
    return NewLogger(ctx, name)
}

// NewSystemLogger 实例系统日志
func NewSystemLogger(ctx context.Context) *Logger {
    return NewLogger(ctx, "system")
}

func NewLogger(ctx context.Context, name string) *Logger {
    return &Logger{
        name:   name,
        ctx:    ctx,
        sn:     sn(),
        writer: writers(name),
    }
}

// sn 生成sn
func sn() string {
    return strconv.FormatInt(time.Now().UnixNano(), 10)
}

// SetSn 设置新的sn
func (l *Logger) SetSn() {
    l.sn = sn()
}

// System 标准日志
func (l *Logger) System(msg string, fields ...Field) {
    l.Log("SYSTEM", msg, fields...)
}

// Info 标准日志
func (l *Logger) Info(msg string, fields ...Field) {
    l.Log("INFO", msg, fields...)
}

// Debug 调试日志
func (l *Logger) Debug(msg string, fields ...Field) {
    l.Log("DEBUG", msg, fields...)
}

// Error 错误日志
func (l *Logger) Error(msg string, fields ...Field) {
    l.Log("ERROR", msg, fields...)
}

// Log 写入log
func (l *Logger) Log(level, msg string, fields ...Field) {
    _, _ = l.writer.Write([]byte(l.format(level, msg, fields...)))
}

// 格式化日志行
func (l *Logger) format(level, msg string, fields ...Field) string {
    t := time.Now().Format("2006-01-02 15:04:05.000000")

    // 时间
    b := strings.Builder{}
    b.WriteString(wrap)
    b.WriteString(t)
    b.WriteString(splicing)

    // sn
    b.WriteString(l.sn)
    b.WriteString(splicing)

    // level
    b.WriteString(level)
    b.WriteString(splicing)

    // 消息标记
    b.WriteString(msg)

    if l.prefix != "" {
        // prefix
        b.WriteString(splicing)
        b.WriteString(l.prefix)
    }

    for _, field := range fields {
        bf := strings.Builder{}
        bf.WriteString(field.Key)
        bf.WriteString(separator)
        bf.WriteString(field.Val)

        b.WriteString(splicing)
        b.WriteString(bf.String())
    }

    if l.suffix != "" {
        // suffix
        b.WriteString(splicing)
        b.WriteString(l.suffix)
    }

    return b.String()
}
